package day1219_test;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client2 {
    //一.main方法中： 用构造方法创建客户端对象<构造方法中会通过ip和端口连接服务器>. 然后用start方法启动客户端
    public static void main(String[] args) throws IOException {
        Client2 c=new Client2();//1.1.用构造方法创建客户端对象<构造方法中会通过ip和端口连接服务器>
        c.start();//1.2.然后用start方法启动客户端
    }

    //二.客户端的构造方法，用new Socket(信息)连接服务器
    Socket s=null;
    Client2() throws IOException {
        //1.构造方法，用new Socket(信息)连接服务器
        s=new Socket("127.0.0.1",8088);
    }//如果要用此客户端连接别人的服务端，需要两个电脑处于同一个局域网中，并将"127.0.0.1"改成对方的真实ip地址


    //三.启动客户端的方法
    // (启动一个专门用于接收服务端响应数据的线程<接收响应数据和发送数据是分到两个线程中的，
    // 发送数据的同时可以接收服务器响应的数据>，接收数据在ReceiveFromServer线程，发送数据在main线程中)
    //(main方法调用start方法，start方法用输出流发送数据，所以发送数据在main线程中)
    public void start() throws IOException {
        //3.1.创建接收服务端响应数据的线程对象，并启动此线程。
        //(将socket对象传入到线程中，在线程中用socket的输入流读取服务端响应数据)
        ReceiveFromServer thread=new ReceiveFromServer(s);
        thread.start();//调用线程的start方法启动线程(start方法会调用线程的run方法)

        //3.2.获取Socket的输出流(输出流用于给服务器发送数据)
        OutputStream out=s.getOutputStream();//字节输出流
        OutputStreamWriter  writer=new OutputStreamWriter(out);//字符输出流
        PrintWriter  pw=new PrintWriter(writer);
        //3.3.用输出流给服务器发送数据(在死循环中不断用Scanner读取控制台的数据并用输出流发送到服务端)
        Scanner   sc=new Scanner(System.in);
        while(true){
            System.out.println("请输入您想要发送的消息：");
            String msg=sc.nextLine();//3.3.1.在死循环中用户可以不断用Scanner输入文字(下边用输出流将其发送到服务端)
            pw.println(msg);//3.3.2.用PrintWriter  pw将用户输入的文字发送到服务器
            pw.flush();//3.3.3.flush()方法的作用是：如果主线程只是将要输出的数据暂存到电脑内存中等待输出，则强制用flush方法将数据输出到服务端
        }
    }


    //四、用内部类编写一个线程:在线程里循环读取服务端返回的数据，并打印
    class  ReceiveFromServer  extends  Thread{
        //4.1.将socket通过构造方法保存到内部类的成员变量Socket so中(用于获取Socket中的输入流来读取服务端返回的数据)。
        Socket  so;
        ReceiveFromServer(Socket s){///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            so=s;
        }
        //4.2.在线程的run方法中将Socket中的输入流一层层封装为BufferedReader缓冲字符输入流(为了调用readLine方法一次读取一行文字)
        public  void run(){
            try {
                //4.2.1.run方法中将Socket中的输入流一层层封装为BufferedReader缓冲字符输入流
                BufferedReader br=new BufferedReader(
                        new InputStreamReader (s.getInputStream(),"UTF-8"));
                //4.2.2.用BufferedReader br缓冲字符输入流的readLine方法按行读取服务端返回的数据存入到msg变量中，
                //并在循环中打印msg中接收的服务端返回的响应数据
                String msg=null;
                while(  (msg=br.readLine())!=null ){//用readLine方法按行读取服务端返回的数据存入到msg变量中(如果读取的数据不为null就打印)
                    System.out.println(msg);//打印msg中接收的服务端返回的响应数据
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}


